/*
    This is a set of libraries to assist in OpenGl and Other Applications
    Copyright (C) 2008  The Modular Engine Team

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#define HUDMODULE
#include "HUDWindow.h"

namespace ModularEngine
{

	HUDWindow::HUDWindow()
	{
		msWindowTitle = "No Window Name";
		mpFocusedElement = 0;
		LOADCOLORS;

	}

	HUDWindow::~HUDWindow()
	{
		// Nothing yet.
		// Should probably do some better memory management

	}

	int HUDWindow::initialize()
	{

		return 1;
	}

	void HUDWindow::draw()
	{
		Vector2d cPoint = ModularEngine::WindowModule::getSingleton().getMouse();

		// Move the window first:
		if( mbMouseDown )
		{
			if( !isMouseDown() )
			{
				mbMouseDown = false;
			} else {
				// Calculate an adjustment vector and change all elements accordingly
				// This simulates the window being dragged.
				
				Vector2d adjust = cPoint - mMouseInitial;
				mMouseInitial = cPoint;

				mvPosition = mvPosition + adjust;

				for( std::vector<HUDElement *>::iterator i = mvElements.begin(); i != mvElements.end(); i++ )
				{
					(*i)->mvPosition = (*i)->mvPosition + adjust;
				}
			}
		}

		gl->resetCoords();
		gl->setCoords( mvPosition );
		glPushMatrix();
		// draw here 

		// Draw the window first

		// Drop shadow.  Hey we're not all fun and games here.
		glColor4f( 0, 0, 0, .40 );
		gl->drawRect( Vector2d( 3, 3 ), mvDimensions );

		// Window Border
		if( HUDModule::getSingleton().mpFocusedElement == this )
			glColor3f( mvTextColor.x, mvTextColor.y, mvTextColor.z );
		else
			glColor3f( mvBaseColor.x, mvBaseColor.y, mvBaseColor.z );

		// Window itself
		gl->drawRect( Vector2d( 0, 0 ), mvDimensions );
		gl->setCoords( mvPosition + Vector2d( 1, 1 ) );
		gl->drawGradientRect( Vector2d(0, 0), Vector2d( mvDimensions.x-2, 20 ), mvBaseColor-.2,  mvBaseColor );
		gl->drawGradientRect( Vector2d(0, 20), Vector2d( mvDimensions.x-2, mvDimensions.y-22 ), mvBaseColor-.2, mvBaseColor+.2 );

		glColor3f( mvTextColor.x, mvTextColor.y, mvTextColor.z );

		gl->drawText( (char *)msWindowTitle.c_str(), Vector2d( 4, 0 ) );

		// TODO: Figure out a way of clipping all the elements.
		// A stencil test won't cut it.

		// Then draw everything else over it.
		for( std::vector<HUDElement *>::iterator i = mvElements.begin(); i != mvElements.end(); i++ )
		{
			(*i)->draw();
		}

		
		
		glPopMatrix();
		
	}

	void HUDWindow::mouseInput(ModularEngine::Vector2d vPos, UINT nDown)
	{

		float X = vPos.x;
		float Y = vPos.y;

		if( vPos.y < mvPosition.y + 25 )
		{
			// Drag the window.
			mMouseInitial = vPos;
			mbMouseDown = true;
			return;
		}

		// Go through the list backwards.  
		// The first one that has the mouse focus gets the input because the last one drawn appears on top
		for( std::vector<HUDElement *>::reverse_iterator i = mvElements.rbegin(); i != mvElements.rend(); i++ )
		{
			// If the mouse is in the boundaries, then the mouse is clicking in this element.
			if( gl->pointInRect( Vector2d( X, Y ),  (*i)->mvPosition, (*i)->mvDimensions ) )
			{
				// Temporarily store current iterator in a pointer
				HUDElement *element = *i;
				// i+1 because... it just works.
				// Remove this iterator so that it can be pushed on top of the list
				mvElements.erase( (i+1).base() );
				// Push the element on top of the list
				mvElements.push_back( element );
				// Set mpFocusedElement to element
				mpFocusedElement = element;
				// Send the input
				element->mouseInput( Vector2d( X, Y ), nDown );
				return;
				// give focus
			}
		}

	}

	void HUDWindow::addElement( HUDElement *pElement )
	{
		// Initialize the element, put it on the list, and adjust its position to the window its in.
		pElement->initialize();
		mvElements.push_back( pElement );
		pElement->mvPosition = pElement->mvPosition + mvPosition + Vector2d( 1, 22 );
		// Last element on gains focus
		mpFocusedElement = pElement;

		pElement->pParent = this;

	}

	void HUDWindow::keyboardInput( UINT nKey )
	{
		// Send all key inputs to the focused element
		if( mpFocusedElement )
			mpFocusedElement->keyboardInput( nKey );
	}


}
